/*
 * @Author: czy
 * @Date: 2021-04-26 07:41:28
 * @LastEditTime: 2021-06-04 16:37:23
 */
#include "const.h"
#include "libio.h"
#include "string.h"

#include "shell.h"
#include "stdio.h"
#include "stdlib.h"
#include "map.h"

#include "api/system.h"

static Map map = newMap(command *);

/**
 * @description: Add a command to the command list.
 * @param name          Name of the command.
 * @param help_content  Help content of the command
 * @param func          Function.
 */
void addNewCmd(char *name, char *help_content, int (*func)(int argc, char *argv[]))
{
    command cmd;
    strcpy(cmd.name, name);
    strcpy(cmd.help_content, help_content);
    cmd.func = func;
    map.set(&map, name, &cmd);
    command *temp = (command *)map.get(&map, name);
    addenv("command", name);
}

/**
 * @description: Match the input command with the registered command.
 * @param name  Name of command.
 * @param cmd   Matching command.
 * @return TRUE if match, else FALSE.
 */
int match(char *name, command *cmd)
{
    command *temp;
    temp = (command *)map.get(&map, name);
    if (temp != NULL)
    {
        memcpy(cmd, temp, sizeof(command));
        return TRUE;
    }
    return FALSE;
}

/**
 * @description: Initialization of shell.
 */
static void init(void)
{
    printf("Press any key to start shell...");
    register_command();
    extern void memTestCaseInit(void);
    memTestCaseInit();
    getchar();
    clear();
}

/**
 * @description: Submit the current instruction to the shell.
 */
static void submit(char *str)
{
    int argc;
    char *argv[MAX_ARGC];
    command cmd;
    argc = split(argv, str, " ");
    if (argc == 1 && *argv[0] == '\0')
    {
        return;
    }
    if (match(argv[0], &cmd))
    {
        cmd.func(argc, argv);
    }
    else
    {
        printf("%s: command not found\n", argv[0]);
    }
}

/**
 * @description: Start shell.
 */
void startShell(void)
{
    char str[BUFFER] = "";
    init();
    while (TRUE)
    {
        printf(PROMPT);
        submit(read(str, PROMPT, stdout->stream));
        strzero(str, BUFFER);
    }
}
